import unittest
import json

from sqlalchemy import update

import dao


class DaoTest(unittest.TestCase):

    def setUp(self) -> None:
        super().setUp()
        dao.create_all_tables()

    def tearDown(self) -> None:
        super().tearDown()
        sess = dao.Session()
        for table in dao.Base.metadata.tables.values():
            sess.execute(table.delete())
        sess.commit()

    def test_add_normal_user(self):
        sess = dao.Session()
        user = dao.User(name="shengnan")
        sess.add(user)
        user_sn = sess.query(dao.User).filter_by(name='shengnan').first()
        self.assertEqual(user_sn.name, "shengnan")
        self.assertIsNotNone(user_sn.id)
        self.assertEqual(user_sn.role, dao.UserRole.NORMAL_USER)

    def test_add_admin_user(self):
        sess = dao.Session()
        user = dao.User(name="shengnan", role=dao.UserRole.POWER_USER)
        sess.add(user)
        user_sn = sess.query(dao.User).filter_by(name='shengnan').first()
        self.assertEqual(user_sn.name, "shengnan")
        self.assertIsNotNone(user_sn.id)
        self.assertEqual(user_sn.role, dao.UserRole.POWER_USER)

    def test_find_user_not_exists(self):
        sess = dao.Session()
        print("Hello, find not exits")
        ret = sess.query(dao.User).filter_by(id=100).first()
        self.assertIsNone(ret)

    def test_create_task(self):
        sess = dao.Session()
        t1 = dao.CodeReviewTask(submit_user_id=10, process_user_id=0, review_url="/path/to/review/url/100")
        sess.add(t1)
        t1q = sess.query(dao.CodeReviewTask).order_by(dao.CodeReviewTask.created_time).all()
        self.assertEqual(len(t1q), 1)
        self.assertEqual(t1q[0].submit_user_id, 10)
        self.assertEqual(t1q[0].process_user_id, 0)
        self.assertEqual(t1q[0].status, dao.TaskStatus.TS_CREATED)

    def test_create_multiple_tasks(self):
        sess = dao.Session()
        for i in range(0, 100):
            t = dao.CodeReviewTask(submit_user_id=i % 10 + 1,
                                   process_user_id=0,
                                   review_url="/path/to/review/url/{}".format(i))
            sess.add(t)
        sess.commit()

        sess = dao.Session()
        tasks = sess.query(dao.CodeReviewTask).order_by(dao.CodeReviewTask.created_time).all()
        self.assertEqual(len(tasks), 100)
        self.assertEqual(tasks[0].status, dao.TaskStatus.TS_CREATED)
        self.assertEqual(tasks[0].priority, dao.Priority.TP_MIDDLE)
        self.assertEqual(tasks[99].status, dao.TaskStatus.TS_CREATED)
        self.assertEqual(tasks[99].priority, dao.Priority.TP_MIDDLE)
        self.assertEqual(tasks[50].status, dao.TaskStatus.TS_CREATED)
        self.assertEqual(tasks[50].priority, dao.Priority.TP_MIDDLE)
        all_task_ids = set()
        for task in tasks:
            all_task_ids.add(task.id)
        self.assertEqual(len(all_task_ids), 100)

    def test_query_in_pages(self):
        pass

    def test_create_update_task_to_done(self):
        sess = dao.Session()
        t1 = dao.CodeReviewTask(submit_user_id=10, process_user_id=0, review_url="/path/to/review/url/100")
        sess.add(t1)
        sess.commit()
        sess = dao.Session()
        t1q = sess.query(dao.CodeReviewTask).order_by(dao.CodeReviewTask.created_time).first()
        t1_update = dao.CodeReviewTask(id=t1q.id, submit_user_id=10, process_user_id=0, review_url="/path/to/review/url/100", status=dao.TaskStatus.TS_DONE)

        t1q = sess.query(dao.CodeReviewTask).order_by(dao.CodeReviewTask.created_time).first()
        self.assertEqual(t1q.status, dao.TaskStatus.TS_CREATED)
        sess.execute(update(dao.CodeReviewTask).where(dao.CodeReviewTask.id == t1_update.id).values(status=dao.TaskStatus.TS_DONE))
        sess.commit()
        t1q = sess.query(dao.CodeReviewTask).order_by(dao.CodeReviewTask.created_time).first()
        self.assertEqual(t1q.status, dao.TaskStatus.TS_DONE)
